using MediatR;
using Microsoft.OpenApi.Models;
using Ocelot.Configuration;
using Ocelot.Configuration.Repository;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using Ocelot.Provider.Nacos;
using Ocelot.ServiceDiscovery;
using Ocelot.ServiceDiscovery.Providers;
using Scalar.AspNetCore;
using Serilog;
using Service.Core.Behaviors;
using Service.Core.Repository;
using Service.Core.Shared;
using Service.Framework;
using Service.Framework.AppStartup;
using Service.Framework.Utils;
using Service.Gateway.Application.Service;
using Service.Gateway.Core;
using Service.Gateway.Core.AgileConfigServiceDiscovery;
using Swashbuckle.AspNetCore.Filters;
using System.Security.Cryptography.X509Certificates;


namespace Service.Gateway;

/// <summary>
/// 程序启动器
/// </summary>
[ImportStartupModule(
    typeof(CoreRepositoryStartup))]
public class ServiceGatewayStartup : AppStartupBase<ServiceGatewayStartup>
{
    /// <summary>
    ///  
    /// </summary>
    /// <param name="webApplicationBuilder"></param>
    public override void ConfigureServices(WebApplicationBuilder webApplicationBuilder)
    {
        base.ConfigureServices(webApplicationBuilder);
        var services = webApplicationBuilder.Services;
        services.AddMediatR(cfg => { cfg.RegisterServicesFromAssemblyContaining(typeof(Program)); });
        services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>)); //注入日志管道捕获请求。
        services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); //注入验证管道捕获请求。
        //注册数据库配置网关
        services.AddSingleton<IFileConfigurationRepository, DbServerFileConfigurationRepository>();
        services.AddHostedService<FileConfigurationPoller>();

        var appName = Tools.GetAppName(webApplicationBuilder.Environment.ApplicationName);
        var namespacePrefix = Tools.GetNamespacePrefix(webApplicationBuilder.Environment.ApplicationName);
        // Swagger 注册Swagger生成器，定义一个和多个Swagger 文档
        services.AddSwaggerGen(options =>
        {
            options.AddServer(new OpenApiServer()
            {
                Url = $"/{appName}",
                Description = appName + "：swagger接口开发文档",
            });
            options.CustomSchemaIds(type => type.FullName);

            options.SwaggerDoc("v1", new OpenApiInfo
            {
                Title = appName,
            });

            //为 Swagger JSON and UI设置xml文档注释路径
            Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory)
                .Where(w => w.EndsWith(".xml") && w.Contains(namespacePrefix))
                .Select(w => w)
                .ToList()
                .ForEach(w =>
                {
                    options.IncludeXmlComments(w, true);
                });
            #region Jwt token 配置

            //添加Jwt验证设置,添加请求头信息
            options.AddSecurityRequirement(new OpenApiSecurityRequirement
            {
                {
                    new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference
                        {
                            Id = "Bearer",
                            Type = ReferenceType.SecurityScheme
                        }
                    },
                    new List<string>()
                }
            });

            options.OperationFilter<AddResponseHeadersFilter>();
            options.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
            //很重要！这里配置安全校验，和之前的版本不一样
            options.OperationFilter<SecurityRequirementsOperationFilter>();
            // options.OperationFilter<FileUploadOperation>();
            //开启 oauth2 安全描述
            options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
            {
                Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}（注意两者之间是一个空格）\"",
                In = ParameterLocation.Header,
                Name = "",
                Type = SecuritySchemeType.ApiKey,
                //Scheme = "basic",
            });

            #endregion
        });

        if (webApplicationBuilder.Configuration.GetSection("Nacos").Exists())
        {
            //添加Ocelot服务发现，适配nacos
            webApplicationBuilder.Services.AddOcelot()
                .AddNacosDiscovery("Nacos")
                .AddDelegatingHandler<IgnoreSSLValidateDelegatingHandler>(true);
        }
        if (webApplicationBuilder.Configuration.GetSection("AgileConfig").Exists())
        {
            webApplicationBuilder.Host.UseAgileConfig();
            webApplicationBuilder.Services.AddOcelot().AddAgileConfigDiscovery();
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="webApplication"></param>
    public override void Configure(WebApplication webApplication)
    {
        base.Configure(webApplication);
        var gatewayService = webApplication.Services.GetService<IGatewayService>();
        var nacosServices = gatewayService.QueryApiGatewayList().Result;
        if (webApplication.Environment.IsDevelopment())
        {
            // 启用Swagger中间件
            webApplication.UseSwagger();
            // 配置SwaggerUI
            webApplication.UseSwaggerUI(c =>
            {
                nacosServices.ForEach(s =>
                {
                    c.RoutePrefix = "";
                    c.SwaggerEndpoint($"{s.RouteId}/swagger/v1/swagger.json", s.RouteId);
                });
            });

            webApplication.MapScalarApiReference(options =>
            {
                var documents = new List<ScalarDocument>();
                foreach (var s in nacosServices)
                {
                    documents.Add(new ScalarDocument("v1", s.RouteId, $"{s.RouteId}/swagger/v1/swagger.json"));
                }
                options.AddDocuments(documents);
                // Bearer
                options
                    .WithHttpBearerAuthentication(bearer =>
                    {
                        bearer.Token = "your-bearer-token";
                    });
            });


        }
        webApplication.UseOcelot().Wait();
    }

    /// <summary>
    /// 程序启动
    /// </summary>
    /// <param name="webApplication"></param>
    public override void ApplicationStarted(WebApplication webApplication)
    {

        Log.Information("gateway-------------------------------启动");
    }


    /// <summary>
    /// 
    /// </summary>
    public class IgnoreSSLValidateDelegatingHandler : DelegatingHandler
    {
        private readonly X509CertificateCollection _certificates = new X509CertificateCollection();
        public IgnoreSSLValidateDelegatingHandler()
        {
        }
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            var inner = InnerHandler;
            while (inner is DelegatingHandler)
            {
                inner = ((DelegatingHandler)inner).InnerHandler;
            }
            // inner is HttpClientHandler
            if (inner is HttpClientHandler httpClientHandler)
            {
                if (httpClientHandler.ServerCertificateCustomValidationCallback == null)
                {
                    httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
                    {
                        return true;
                    };
                }
            }
            return await base.SendAsync(request, cancellationToken);
        }
    }
}